home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Format CD 42
/
Amiga Format AFCD42 (Issue 126, Aug 1999).iso
/
-serious-
/
comms
/
other
/
slrn
/
slrn_src
/
src
/
clientlib.c
< prev
next >
Wrap
C/C++ Source or Header
|
1999-05-14
|
22KB
|
1,026 lines
/* -*- mode: C; mode: fold; -*- */
/* This file is a MESS. For that reason, I wrote sltcp.c which I regard as
* much cleaner. I tried to clean this up but with at least 4 different
* TCP/IP implementations for VMS as well as TLI and BSD, there is not too
* much hope. The routines in sltcp.c should be adequate for most Unix
* systems as well as OS/2. Until VMS standardizes its TCP/IP interface
* the routines in this file will have to be used.
*
* Much of this file has been totally re-written. Now all read/writes are
* to a file descriptor. All reads take place via the function
* 'client_read' and all writes are done in 'client_write'. These functions
* call the appropriate low level functions to perform the actual operation.
* Specifically, client_read calls:
*
* socket_read (MULTINET)
* do_netlib_read (NETLIB)
* read (everything else)
*
* and client_write calls:
*
* netlib_write (NETLIB)
* socket_write (MULTINET)
* write (everything else)
*
* JED.
*/
/*
* This software is Copyright 1991 by Stan Barber.
*
* Permission is hereby granted to copy, reproduce, redistribute or otherwise
* use this software as long as: there is no monetary profit gained
* specifically from the use or reproduction or this software, it is not
* sold, rented, traded or otherwise marketed, and this copyright notice is
* included prominently in any copy made.
*
* The author make no claims as to the fitness or correctness of this software
* for any use whatsoever, and it is provided as is. Any use of this software
* is at the user's own risk.
*
*/
#if 0
# define DEBUG_FILE "slrn.log"
#endif
#include "config.h"
#include "slrnfeat.h"
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <errno.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#ifdef HAVE_STDLIB_H
# include <stdlib.h>
#endif
#include <sys/types.h>
#ifdef VMS
/*{{{ VMS includes */
# include "vms.h"
# ifdef MULTINET
# include "multinet_root:[multinet.include.vms]inetiodef.h"
# include "multinet_root:[multinet.include.sys]types.h"
# else
# if NETLIB
# include <descrip.h>
# include <types.h>
# include <iodef.h>
# include <stsdef.h>
# include "netlib_dir:netlibdef.h"
# define NNTP_PORT 119
# define INIT_SDESC(dsc, len, ptr) {(dsc).dsc$b_dtype = DSC$K_DTYPE_T;\
(dsc).dsc$b_class = DSC$K_CLASS_S; (dsc).dsc$w_length = (len);\
(dsc).dsc$a_pointer = (ptr);}
# else
# include <types.h>
# include <iodef.h>
# define NNTP_PORT 119
# endif
# endif
/*}}}*/
#endif
#include <ctype.h>
#ifdef TLI
/*{{{ TLI includes */
# include <fcntl.h>
# include <tiuser.h>
# include <stropts.h>
# include <sys/socket.h>
# define SLRN_LOADED_SYS_SOCKET_H
# ifdef WIN_TCP
# include <sys/in.h>
# else
# include <netinet/in.h>
# define SLRN_LOADED_NETINET_IN_H
# endif
# define IPPORT_NNTP ((unsigned short) 119)
# include <netdb.h> /* All TLI implementations may not have this */
/*}}}*/
#else /* !TLI */
# ifdef VMS
/*{{{ More VMS includes */
# ifdef MULTINET
# include "multinet_root:[multinet.include]netdb.h"
# include "multinet_root:[multinet.include.sys]socket.h"
# include "multinet_root:[multinet.include.netinet]in.h"
# define SLRN_LOADED_NETINET_IN_H
# define SLRN_LOADED_SYS_SOCKET_H
# endif
# ifdef NETLIB
# include <descrip.h>
# include "netlib_dir:netlibdef.h"
# endif
# ifdef UCX
# include <netdb.h>
# include <socket.h>
# include <in.h>
# include <inet.h>
# endif
/*}}}*/
# else /* !VMS */
# include <sys/socket.h>
# include <netinet/in.h>
# define SLRN_LOADED_NETINET_IN_H
# define SLRN_LOADED_SYS_SOCKET_H
# ifndef EXCELAN
# include <netdb.h>
# endif /* !EXCELAN */
# endif /* !VMS */
#endif /* !TLI */
#ifdef HAVE_SYS_SOCKET_H
# ifndef SLRN_LOADED_SYS_SOCKET_H
# include <sys/socket.h>
# define SLRN_LOADED_SYS_SOCKET_H
# endif
#endif
#ifdef HAVE_NETINET_IN_H
# ifndef SLRN_LOADED_NETINET_IN_H
# include <netinet/in.h>
# define SLRN_LOADED_NETINET_IN_H
# endif
#endif
#ifdef HAVE_ARPA_INET_H
# ifndef SLRN_LOADED_ARPA_INET_H
# include <arpa/inet.h>
# define SLRN_LOADED_ARPA_INET_H
# endif
#endif
#ifdef __unix__
# ifdef MULTINET
# undef MULTINET
# endif
# ifdef NETLIB
# undef NETLIB
# endif
#endif
#ifdef EXCELAN
/*{{{ EXCELAN defines */
# define NNTP_PORT ((unsigned short) 119)
# if __STDC__
int connect(int, struct sockaddr *);
unsigned short htons(unsigned short);
unsigned long rhost(char **);
int rresvport( int );
int socket( int, struct sockproto *, struct sockaddr_in *, int );
# endif
/*}}}*/
#endif
#ifdef DECNET
# include <netdnet/dn.h>
# include <netdnet/dnetdb.h>
#endif /* DECNET */
#include "clientlib.h"
#include "server.h"
#include "misc.h"
#ifndef NNTP_PORT
# define NNTP_PORT 119
#endif
#ifdef NEEDS_EXTERN_DECLARATIONS
# define DECLARE_EXTERN(x) extern x;
#else
# define DECLARE_EXTERN(x)
#endif
#ifdef NETLIB
static void *Socket_Fd;
#else
static int Socket_Fd;
#endif
#ifdef DEBUG_FILE
static FILE *Debug_Fp;
#endif
static int Server_Has_Been_Closed = 1;
static void client_close_server(void);
static int get_tcp_socket(char *, int);
static void reset_read_buffer (void);
/*{{{ client_server_init_1 */
/*
* client_server_init Get a connection to the remote news server.
*
* Parameters: "machine" is the machine to connect to.
*
* Returns: -1 on error
* server's initial response code on success.
*
* Side effects: Connects to server.
*/
static int client_server_init_1 (char *machine, int port)
{
int sockt_rd;
#ifdef DECNET
char *cp;
cp = slrn_strchr(machine, ':');
if (cp && cp[1] == ':')
{
*cp = '\0';
sockt_rd = get_dnet_socket(machine);
}
else
sockt_rd = get_tcp_socket(machine, port);
#else
sockt_rd = get_tcp_socket (machine, port);
#endif
if (sockt_rd < 0)
return (-1);
#ifndef NETLIB
Socket_Fd = sockt_rd;
#endif
/* Now get the server's signon message */
#ifdef DEBUG_FILE
Debug_Fp = fopen (DEBUG_FILE, "w");
#endif
return 0;
}
/*}}}*/
/*{{{ get_tcp_socket */
/*
* get_tcp_socket -- get us a socket connected to the news server.
*
* Parameters: "machine" is the machine the server is running on.
*
* Returns: Socket connected to the news server if
* all is ok, else -1 on error.
*
* Side effects: Connects to server.
*
* Errors: Printed via perror.
*/
static int get_tcp_socket(char *machine, int nntpport)
{
#ifndef NETLIB
int s = -1;
struct sockaddr_in s_in;
#endif
#ifdef TLI
char *t_alloc();
struct t_call *callptr;
/*
* Create a TCP transport endpoint.
*/
if ((s = t_open("/dev/tcp", O_RDWR, (struct t_info*) 0)) < 0)
{
t_error("t_open: can't t_open /dev/tcp");
return(-1);
}
if(t_bind(s, (struct t_bind *)0, (struct t_bind *)0) < 0)
{
t_error("t_bind");
t_close(s);
return(-1);
}
memset ((char *) &s_in, 0, sizeof(s_in));
s_in.sin_family = AF_INET;
if (nntpport < 0) nntpport = NNTP_PORT;
s_in.sin_port = htons((unsigned short) nntpport);
if (!isdigit(*machine) ||
(long)(s_in.sin_addr.s_addr = inet_addr(machine)) == -1)
{
struct hostent *gethostbyname(), *hp;
if((hp = gethostbyname(machine)) == NULL)
{
fprintf(stderr,"gethostbyname: %s: host unknown\n",
machine);
t_close(s);
return(-1);
}
memcpy ((char *) &s_in.sin_addr, hp->h_addr, hp->h_length);
}
/*
* Allocate a t_call structure and initialize it.
* Let t_alloc() initialize the addr structure of the t_call structure.
*/
if ((callptr = (struct t_call *) t_alloc(s,T_CALL,T_ADDR)) == NULL)
{
t_error("t_alloc");
t_close(s);
return(-1);
}
callptr->addr.maxlen = sizeof(s_in);
callptr->addr.len = sizeof(s_in);
callptr->addr.buf = (char *) &s_in;
callptr->opt.len = 0; /* no options */
callptr->udata.len = 0; /* no user data with connect */
/*
* Connect to the server.
*/
if (t_connect(s, callptr, (struct t_call *) 0) < 0)
{
t_error("t_connect");
t_close(s);
return(-1);
}
/*
* Now replace the timod module with the tirdwr module so that
* standard read() and write() system calls can be used on the
* descriptor.
*/
if